import datetime

from absl import (app, flags)
import pandas as pd
import pytz

from coin.base.datetime_util import to_timestamp_int
from coin.base.datetime_util import convert_string_to_dates
from coin.exchange.base.strategy_logger import parse_file_name
from coin.support.proto_log.logic.util import (
    enumerate_strat_log_into_stratinfos,
    StratInfo)
from coin.tool.strat_monitor.util.monitor_util import get_active_strategy
from xunkemgmt_client.tool.slack_noti import send_to_slack
from coin.base.query_util import query_pta


FLAGS = flags.FLAGS


def _get_strat_info_from_pta_db(trading_date):
  result = query_pta(
    trading_date, trading_date,
    business_units=['Coin', 'Day1mm', 'Prex'], pta_type='STRATEGY')
  result = result.drop_duplicates(subset=['strategy_name', 'machine'])
  strat_info = [
      StratInfo(strategy_name=summary['strategy_name'],
        machine=summary['machine'], trading_date=trading_date)
        for _, summary in result.iterrows()
  ]
  return strat_info


def _check_log_not_archived(trading_date, strat_info_from_archive):
  diff = []
  strat_info_from_db = _get_strat_info_from_pta_db(trading_date)
  strat_info_set = set([(strat_info.strategy_name, strat_info.machine) for strat_info
                         in strat_info_from_archive])
  for strat_info in strat_info_from_db:
    if (strat_info.strategy_name, strat_info.machine) not in strat_info_set:
      diff.append(strat_info._asdict())
  diff_msg = ''
  if len(diff) != 0:
    diff_df = pd.DataFrame(diff)
    diff_msg = '\nStrat log not archived:\n' + \
               diff_df.sort_values(by='machine').to_string(index=False)
  return diff_msg


def _check_log_not_registered(trading_date, strat_info_from_archive):
  diff = []
  threshold = to_timestamp_int(datetime.datetime.combine(
        trading_date, datetime.time.min.replace(tzinfo=pytz.UTC)))
  strat_list = get_active_strategy(update_timestamp_threshold=threshold)
  for strat_info in strat_info_from_archive:
    if strat_info.strategy_name not in strat_list:
      diff.append(strat_info._asdict())
  diff_msg = ''
  if len(diff) != 0:
    diff_df = pd.DataFrame(diff)
    diff_msg = '\nStrat log not registered:\n' + \
               diff_df.sort_values(by='machine').to_string(index=False)
  return diff_msg


def _check_archive(trading_date, root_dir, slack_receiver):
  td_str = trading_date.strftime('%Y%m%d')
  strat_info_from_archive = enumerate_strat_log_into_stratinfos(
      root_dir, td_str, parse_file_name)
  msg = f'{root_dir}:\n'
  msg += '%s' % _check_log_not_archived(trading_date, strat_info_from_archive)
  msg += '%s' % _check_log_not_registered(trading_date, strat_info_from_archive)
  print(msg)
  if slack_receiver is not None:
    msg = '```' + msg + '```'
    send_to_slack(msg, slack_receiver, 'msg')


def main(_):
  assert FLAGS.trading_date
  trading_date = convert_string_to_dates(FLAGS.trading_date)[0]
  _check_archive(trading_date, FLAGS.root_dir, FLAGS.slack_receiver)


if __name__ == '__main__':
  flags.DEFINE_string('trading_date', None, 'Trading date in form of %Y%m%d.')

  flags.DEFINE_string('root_dir', '/remote/iosg/strat-1/buckets/log.raw.coin/live//strat_proto_log', '')

  flags.DEFINE_string('slack_receiver', None, 'slack_receiver')
  app.run(main)
